home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 422_02 / cutil / obscure.c < prev    next >
C/C++ Source or Header  |  1994-03-20  |  8KB  |  281 lines

  1. /*
  2.  * Program to obscure the meaning of a MICRO-C source file by
  3.  * removing comments, indenting, and line spacing. All non-reserved
  4.  * words are replaced with meaningless numeric names.
  5.  *
  6.  * Syntax:    obscure <input_file> [output_file] [options]
  7.  *
  8.  * Options:    k=<filename>    - File of names to KEEP (1 per line).
  9.  *            d=<filename>    - File of names to PRE-DEFINE (1 per line).
  10.  *            p=<string>        - Prefix pre-pended to generated numeric names.
  11.  *
  12.  * Use 'k=' to prevent certain names from being obscured.
  13.  * Use 'd=' to insure that certain names will have the same obscured
  14.  * name in several modules (For "extern"s etc.).
  15.  * Default 'p=' prefix is '_'.
  16.  *
  17.  * For MAXIMUM obscuring, use the pre-processor (MCP) before processing
  18.  * with this program. This will remove all pre-processor directives, but BE
  19.  * WARNED that this will make the program LESS PORTABLE, since key system
  20.  * header files (Such as <stdio.h>) will not be re-used when moving to a
  21.  * a new system.
  22.  *
  23.  * Copyright 1989-1994 Dave Dunfield
  24.  * All rights reserved.
  25.  *
  26.  * Permission granted for personal (non-commercial) use only.
  27.  *
  28.  * Compile command: cc obscure -fop
  29.  */
  30. #include <stdio.h>
  31.  
  32. #define NUMNEW        500        /* maximum number of unique words */
  33. #define NUMKEEP        100        /* maximum number of kept words */
  34. #define FREEPOOL    15000    /* size of free storage pool */
  35. #define MAXWIDTH    70        /* maximum width of output line */
  36.  
  37. /* table of reserved words to keep without changing */
  38. char *resword[] = {
  39.         /* MICRO-C keywords */
  40.     "break", "case", "char", "continue", "default", "do", "else",
  41.     "extern", "for", "goto", "if", "int", "register", "return", "static",
  42.     "switch", "unsigned", "while", "include", "define", "endif" ,"ifdef",
  43.     "ifndef", "undef", "forget", "struct", "union", "sizeof",
  44.         /* MICRO-C library functions */
  45.     "abort", "fprintf", "islower", "peekw", "strchr", "abs", "fwrite",
  46.     "isspace", "poke", "strcmp", "atoi", "fputs", "isupper", "pokew",
  47.     "strcpy", "cd", "free", "longjmp", "printf", "strlen", "concat",
  48.     "fscanf", "malloc", "putc", "strncat", "create", "fseek", "max",
  49.     "rename", "strncmp", "delete", "ftell", "memcpy", "rewind", "strncpy",
  50.     "exit", "getc", "memset", "rmdir", "strstr", "fclose", "getenv", "min",
  51.     "scanf", "system", "fread", "getdir", "mkdir", "setjmp", "toupper",
  52.     "fgets", "in", "nargs", "sprintf", "tolower", "find_first", "inw",
  53.     "out", "sscanf", "find_next", "isalpha", "outw", "strbeg", "fopen",
  54.     "isdigit", "peek", "strcat", "alloc_seg", "vdraw_box", "get_es", "tsr",
  55.     "Cclose", "vtstc", "enable", "get_time", "updatexy", "Cgetc", "rand",
  56.     "vclear_box", "exec", "gotoxy", "version", "Copen", "clear_eol",
  57.     "free_seg", "vgets", "Cputc", "clear_eos", "Ctestc", "resize_seg",
  58.     "Csignals", "clscr", "get_attr", "set_attr", "isalnum", "fflush",
  59.     "vopen", "vgetc", "vputc", "vmenu", "copy_seg", "get_cs", "vmessage",
  60.     "cursor_off", "cursor_line", "cursor_block", "get_date", "set_date",
  61.     "set_drive", "vprintf", "get_drive", "set_es", "vputf", "disable",
  62.     "get_ds", "set_time", "vputs", "save_video", "restore_video", "main",
  63.     "open", "close", "read", "write", "lrewind", "lseek", "ltell", "lprintf",
  64.     "lgetc", "lputc", "lgets", "lputs", "setbuf", "cpu", "int86",
  65.         /* Common header file definitions */
  66.     "FILE", "EOF", "NULL", "stdin", "stdout", "stderr", "mc", "h", "comm",
  67.     "console", "ctype", "file", "stdio", "tsr", "window", "video",
  68.     0 };
  69.  
  70. unsigned new_count = 0, keep_count = 0, width = 0;
  71.  
  72. int    inpos = -1;
  73.  
  74. char *new_text[NUMNEW], *keep_text[NUMKEEP], buffer[200],
  75.     free_text[FREEPOOL], *free_ptr, *prefix = "_", pflag = 0;
  76.  
  77. FILE *fpr = 0, *fpw;
  78.  
  79. /*
  80.  * Main program
  81.  */
  82. main(argc, argv)
  83.     int argc;
  84.     char *argv[];
  85. {
  86.     int chr, chr1, i;
  87.     char *ptr;
  88.     FILE *fp;
  89.  
  90.     free_ptr = free_text;
  91.  
  92.     fpw = stdout;
  93.     for(i=1; i < argc; ++i) {
  94.         ptr = argv[i];
  95.         switch((*ptr++ << 8) | *ptr++) {
  96.             case 'p=' :        /* define generation prefix */
  97.                 prefix = ptr;
  98.                 break;
  99.             case 'd=' :        /* define symbols in advance */
  100.                 fp = fopen(ptr, "rvq");
  101.                 while(fgets(buffer, 100, fp)) {
  102.                     new_text[new_count++] = free_ptr;
  103.                     ptr = buffer;
  104.                     do
  105.                         *free_ptr++ = *ptr;
  106.                     while(*ptr++); }
  107.                 fclose(fp);
  108.                 break;
  109.             case 'k=' :        /* define names to keep */
  110.                 fp = fopen(ptr, "rvq");
  111.                 while(fgets(buffer, 100, fp)) {
  112.                     keep_text[keep_count++] = free_ptr;
  113.                     ptr = buffer;
  114.                     do
  115.                         *free_ptr++ = *ptr;
  116.                     while(*ptr++); }
  117.                 fclose(fp);
  118.                 break;
  119.             default:            /* filename */
  120.                 if(!fpr)
  121.                     fpr = fopen(argv[i], "rvq");
  122.                 else if(fpw == stdout)
  123.                     fpw = fopen(argv[i], "wvq");
  124.                 else
  125.                     abort("Too many operands\n"); } }
  126.  
  127. /* if no input file specified, report error */
  128.     if(!fpr) {
  129.         fputs("\nUse: obscure <input_file> [output_file d=definefile k=keepfile p=prefix]\n", stderr);
  130.         abort("\nCopyright 1989-1994 Dave Dunfield\nAll rights reserved.\n"); }
  131.  
  132.     keep_text[keep_count] = new_text[new_count] = 0;
  133.  
  134.     while((chr = read_char()) >= 0) {
  135. top:    switch(chr) {
  136.             case '\n' :        /* newline */
  137.                 if(pflag) {
  138.                     putc('\n', fpw);
  139.                     pflag = width = 0; }
  140.             case '\t' :        /* ignore tab */
  141.             case ' '  :        /* ignore space */
  142.                 break;
  143.             case '/' :        /* starting comment */
  144.                 if((chr = read_char()) == '*') {
  145.                     do
  146.                         if((chr1 = read_char()) < 0)
  147.                             abort("End of file in comment\n");
  148.                     while((chr = (chr << 8) + chr1) != '*/'); }
  149.                 else {
  150.                     write_char('/');
  151.                     goto top; }
  152.                 break;
  153.             case '"' :        /* string input */
  154.             case '\'':        /* character input */
  155.                 buffer[i=0] = chr;
  156.                 do {
  157.                     buffer[++i] = chr1 = read_char();
  158.                     if(chr1 == '\\')
  159.                         buffer[++i] = read_char(); }
  160.                 while(chr1 != chr);
  161.                 buffer[++i] = 0;
  162.                 check_width(width+i);
  163.                 write_string(buffer);
  164.                 break;
  165.             case '#' :        /* pre-processor statements */
  166.                 if(!inpos) {
  167.                     pflag = -1;
  168.                     if(width) {
  169.                         putc('\n', fpw);
  170.                         width = 0; } }
  171.             default:        /* all other characters */
  172.                 if(isvar(chr)) {            /* Variable name */
  173.                     check_width(width);
  174.                     buffer[i = 0] = chr;
  175.                     do
  176.                         buffer[++i] = chr = read_char();
  177.                     while(isvar(chr) || isdigit(chr));
  178.                     buffer[i] = 0;
  179.                     if((!lookup(resword)) && !lookup(keep_text)) {
  180.                         if(!(chr1 = lookup(new_text))) {
  181.                             new_text[new_count++] = free_ptr;
  182.                             ptr = buffer;
  183.                             do
  184.                                 *free_ptr++ = *ptr;
  185.                             while(*ptr++);
  186.                             new_text[chr1 = new_count] = 0; }
  187.                         sprintf(buffer, "%s%u", prefix, chr1); }
  188.                     write_string(buffer);
  189.                     while(isspace(chr)) {
  190.                         if(pflag && (chr == '\n'))
  191.                             break;
  192.                         chr = read_char(); }
  193.                     if(isvar(chr) || isdigit(chr))
  194.                         write_char(' ');
  195.                     goto top; }
  196.                 else if(isdigit(chr)) {        /* number */
  197.                     check_width(width);
  198.                     do
  199.                         write_char(chr);
  200.                     while(isdigit(chr = read_char()));
  201.                     if(chr == 'x') {
  202.                         do {
  203.                             write_char(chr);
  204.                             chr = read_char(); }
  205.                         while(isxdigit(chr)); }
  206.                     goto top; }
  207.                 else
  208.                     write_char(chr); } }
  209.     fclose(fpw);
  210. }
  211.  
  212. /*
  213.  * Lookup the buffered word in a table
  214.  */
  215. lookup(table)
  216.     char *table[];
  217. {
  218.     int i;
  219.     char *ptr;
  220.  
  221.     i = 0;
  222.     while(ptr = table[i++])
  223.         if(!strcmp(buffer, ptr))
  224.             return i;
  225.     return 0;
  226. }
  227.  
  228. /*
  229.  * Test for valid variable character
  230.  */
  231. isvar(chr)
  232.     char chr;
  233. {
  234.     return    ((chr >= 'a') && (chr <= 'z')) ||
  235.             ((chr >= 'A') && (chr <= 'Z')) ||
  236.             (chr == '_');
  237. }
  238.  
  239. /*
  240.  * Read a character from the input file
  241.  */
  242. read_char()
  243. {
  244.     char chr;
  245.  
  246.     inpos = ((chr = getc(fpr)) == '\n') ? -1 : inpos + 1;
  247.     return chr;
  248. }
  249.         
  250. /*
  251.  * Write a character to the file
  252.  */
  253. write_char(chr)
  254.     char chr;
  255. {
  256.     putc(chr, fpw);
  257.     ++width;
  258. }
  259.  
  260. /*
  261.  * Write a string to the file
  262.  */
  263. write_string(string)
  264.     char *string;
  265. {
  266.     while(*string) {
  267.         putc(*string++, fpw);
  268.         ++width; }
  269. }
  270.  
  271. /*
  272.  * Check for over width in output file
  273.  */
  274. check_width(value)
  275.     unsigned value;
  276. {
  277.     if(value >= MAXWIDTH) {
  278.         putc('\n', fpw);
  279.         width = 0; }
  280. }
  281.